home *** CD-ROM | disk | FTP | other *** search
/ Gekikoh Dennoh Club 5 / Gekikoh Dennoh Club Vol. 5 (Japan).7z / Gekikoh Dennoh Club Vol. 5 (Japan) (Track 01).bin / internet / xip / bjpegb2.lzh / bjpeg.c next >
C/C++ Source or Header  |  1997-09-19  |  17KB  |  527 lines

  1. /*
  2.  * bjpeg.c
  3.  *
  4.  * Modified by K.Shirakata.
  5.  */
  6. /*
  7.  * djpeg.c
  8.  *
  9.  * Copyright (C) 1991-1996, Thomas G. Lane.
  10.  * This file is part of the Independent JPEG Group's software.
  11.  * For conditions of distribution and use, see the accompanying README file.
  12.  *
  13.  * This file contains a command-line user interface for the JPEG decompressor.
  14.  * It should work on any system with Unix- or MS-DOS-style command lines.
  15.  *
  16.  * Two different command line styles are permitted, depending on the
  17.  * compile-time switch TWO_FILE_COMMANDLINE:
  18.  *    djpeg [options]  inputfile outputfile
  19.  *    djpeg [options]  [inputfile]
  20.  * In the second style, output is always to standard output, which you'd
  21.  * normally redirect to a file or pipe to some other program.  Input is
  22.  * either from a named file or from standard input (typically redirected).
  23.  * The second style is convenient on Unix but is unhelpful on systems that
  24.  * don't support pipes.  Also, you MUST use the first style if your system
  25.  * doesn't do binary I/O to stdin/stdout.
  26.  * To simplify script writing, the "-outfile" switch is provided.  The syntax
  27.  *    djpeg [options]  -outfile outputfile  inputfile
  28.  * works regardless of which command line style is used.
  29.  */
  30.  
  31. #include "cdjpeg.h"        /* Common decls for cjpeg/djpeg applications */
  32. #include "jversion.h"        /* for version message */
  33.  
  34. #include <ctype.h>        /* to declare isprint() */
  35.  
  36. #ifdef USE_CCOMMAND        /* command-line reader for Macintosh */
  37. #ifdef __MWERKS__
  38. #include <SIOUX.h>              /* Metrowerks needs this */
  39. #include <console.h>        /* ... and this */
  40. #endif
  41. #ifdef THINK_C
  42. #include <console.h>        /* Think declares it here */
  43. #endif
  44. #endif
  45. #define    __IOCS_INLINE__
  46. #include    <iocslib.h>
  47.  
  48.  
  49. /* Create the add-on message string table. */
  50.  
  51. #define JMESSAGE(code,string)    string ,
  52.  
  53. static const char * const cdjpeg_message_table[] = {
  54. #include "cderror.h"
  55.   NULL
  56. };
  57.  
  58.  
  59. static int    pos_x;
  60. static int    pos_y;
  61.  
  62.  
  63. /*
  64.  * Argument-parsing code.
  65.  * The switch parser is designed to be useful with DOS-style command line
  66.  * syntax, ie, intermixed switches and file names, where only the switches
  67.  * to the left of a given file name affect processing of that file.
  68.  * The main program in this file doesn't actually use this capability...
  69.  */
  70.  
  71.  
  72. static const char * progname;    /* program name for error messages */
  73. static char * outfilename;    /* for -outfile switch */
  74.  
  75.  
  76. LOCAL(void)
  77. usage (void)
  78. /* complain about bad command line */
  79. {
  80.   fprintf(stderr, "usage: %s [switches] ", progname);
  81. #ifdef TWO_FILE_COMMANDLINE
  82.   fprintf(stderr, "inputfile outputfile\n");
  83. #else
  84.   fprintf(stderr, "[inputfile]\n");
  85. #endif
  86.  
  87.   fprintf(stderr, "Switches (names may be abbreviated):\n");
  88.   fprintf(stderr, "  -position X,Y  Specify the right-topmost position of the image\n");
  89.   fprintf(stderr, "  -colors N      Reduce image to no more than N colors\n");
  90.   fprintf(stderr, "  -fast          Fast, low-quality processing\n");
  91. #ifdef NOT_SURPORTED
  92.   fprintf(stderr, "  -grayscale     Force grayscale output\n");
  93. #endif
  94. #ifdef IDCT_SCALING_SUPPORTED
  95.   fprintf(stderr, "  -scale M/N     Scale output image by fraction M/N, eg, 1/8\n");
  96. #endif
  97.   fprintf(stderr, "Switches for advanced users:\n");
  98. #ifdef DCT_ISLOW_SUPPORTED
  99.   fprintf(stderr, "  -dct int       Use integer DCT method%s\n",
  100.       (JDCT_DEFAULT == JDCT_ISLOW ? " (default)" : ""));
  101. #endif
  102. #ifdef DCT_IFAST_SUPPORTED
  103.   fprintf(stderr, "  -dct fast      Use fast integer DCT (less accurate)%s\n",
  104.       (JDCT_DEFAULT == JDCT_IFAST ? " (default)" : ""));
  105. #endif
  106. #ifdef DCT_FLOAT_SUPPORTED
  107.   fprintf(stderr, "  -dct float     Use floating-point DCT method%s\n",
  108.       (JDCT_DEFAULT == JDCT_FLOAT ? " (default)" : ""));
  109. #endif
  110.   fprintf(stderr, "  -dither fs     Use F-S dithering (default)\n");
  111.   fprintf(stderr, "  -dither none   Don't use dithering in quantization\n");
  112.   fprintf(stderr, "  -dither ordered  Use ordered dither (medium speed, quality)\n");
  113. #ifdef QUANT_2PASS_SUPPORTED
  114.   fprintf(stderr, "  -map FILE      Map to colors used in named image file\n");
  115. #endif
  116.   fprintf(stderr, "  -nosmooth      Don't use high-quality upsampling\n");
  117. #ifdef QUANT_1PASS_SUPPORTED
  118.   fprintf(stderr, "  -onepass       Use 1-pass quantization (fast, low quality)\n");
  119. #endif
  120.   fprintf(stderr, "  -maxmemory N   Maximum memory to use (in kbytes)\n");
  121.   fprintf(stderr, "  -verbose  or  -debug   Emit debug output\n");
  122.   exit(EXIT_FAILURE);
  123. }
  124.  
  125.  
  126. LOCAL(int)
  127. parse_switches (j_decompress_ptr cinfo, int argc, char **argv,
  128.         int last_file_arg_seen, boolean for_real)
  129. /* Parse optional switches.
  130.  * Returns argv[] index of first file-name argument (== argc if none).
  131.  * Any file names with indexes <= last_file_arg_seen are ignored;
  132.  * they have presumably been processed in a previous iteration.
  133.  * (Pass 0 for last_file_arg_seen on the first or only iteration.)
  134.  * for_real is FALSE on the first (dummy) pass; we may skip any expensive
  135.  * processing.
  136.  */
  137. {
  138.   int argn;
  139.   char * arg;
  140.  
  141.   /* Set up default JPEG parameters. */
  142.   outfilename = NULL;
  143.   cinfo->err->trace_level = 0;
  144.  
  145.   /* Scan command line options, adjust parameters */
  146.  
  147.   for (argn = 1; argn < argc; argn++) {
  148.     arg = argv[argn];
  149.     if (*arg != '-') {
  150.       /* Not a switch, must be a file name argument */
  151.       if (argn <= last_file_arg_seen) {
  152.     outfilename = NULL;    /* -outfile applies to just one input file */
  153.     continue;        /* ignore this name if previously processed */
  154.       }
  155.       break;            /* else done parsing switches */
  156.     }
  157.     arg++;            /* advance past switch marker character */
  158.  
  159.     if (keymatch(arg, "position", 1)) {
  160.       /* Write position. */
  161.       if (++argn >= argc)    /* advance to next argument */
  162.     usage();
  163.       if (sscanf(argv[argn], "%d,%d", &pos_x, &pos_y) != 2)
  164.     usage();
  165.  
  166.     } else if (keymatch(arg, "colors", 1) || keymatch(arg, "colours", 1) ||
  167.            keymatch(arg, "quantize", 1) || keymatch(arg, "quantise", 1)) {
  168.       /* Do color quantization. */
  169.       int val;
  170.  
  171.       if (++argn >= argc)    /* advance to next argument */
  172.     usage();
  173.       if (sscanf(argv[argn], "%d", &val) != 1)
  174.     usage();
  175.       cinfo->desired_number_of_colors = val;
  176.       cinfo->quantize_colors = TRUE;
  177.  
  178.     } else if (keymatch(arg, "dct", 2)) {
  179.       /* Select IDCT algorithm. */
  180.       if (++argn >= argc)    /* advance to next argument */
  181.     usage();
  182.       if (keymatch(argv[argn], "int", 1)) {
  183.     cinfo->dct_method = JDCT_ISLOW;
  184.       } else if (keymatch(argv[argn], "fast", 2)) {
  185.     cinfo->dct_method = JDCT_IFAST;
  186.       } else if (keymatch(argv[argn], "float", 2)) {
  187.     cinfo->dct_method = JDCT_FLOAT;
  188.       } else
  189.     usage();
  190.  
  191.     } else if (keymatch(arg, "dither", 2)) {
  192.       /* Select dithering algorithm. */
  193.       if (++argn >= argc)    /* advance to next argument */
  194.     usage();
  195.       if (keymatch(argv[argn], "fs", 2)) {
  196.     cinfo->dither_mode = JDITHER_FS;
  197.       } else if (keymatch(argv[argn], "none", 2)) {
  198.     cinfo->dither_mode = JDITHER_NONE;
  199.       } else if (keymatch(argv[argn], "ordered", 2)) {
  200.     cinfo->dither_mode = JDITHER_ORDERED;
  201.       } else
  202.     usage();
  203.  
  204.     } else if (keymatch(arg, "debug", 1) || keymatch(arg, "verbose", 1)) {
  205.       /* Enable debug printouts. */
  206.       /* On first -d, print version identification */
  207.       static boolean printed_version = FALSE;
  208.  
  209.       if (! printed_version) {
  210.     fprintf(stderr, "Independent JPEG Group's DJPEG, version %s\n%s\n",
  211.         JVERSION, JCOPYRIGHT);
  212.     printed_version = TRUE;
  213.       }
  214.       cinfo->err->trace_level++;
  215.  
  216.     } else if (keymatch(arg, "fast", 1)) {
  217.       /* Select recommended processing options for quick-and-dirty output. */
  218.       cinfo->two_pass_quantize = FALSE;
  219.       cinfo->dither_mode = JDITHER_ORDERED;
  220.       if (! cinfo->quantize_colors) /* don't override an earlier -colors */
  221.     cinfo->desired_number_of_colors = 216;
  222.       cinfo->dct_method = JDCT_FASTEST;
  223.       cinfo->do_fancy_upsampling = FALSE;
  224.  
  225.     } else if (keymatch(arg, "grayscale", 2) || keymatch(arg, "greyscale",2)) {
  226.       /* Force monochrome output. */
  227.       cinfo->out_color_space = JCS_GRAYSCALE;
  228.  
  229.     } else if (keymatch(arg, "map", 3)) {
  230.       /* Quantize to a color map taken from an input file. */
  231.       if (++argn >= argc)    /* advance to next argument */
  232.     usage();
  233.       if (for_real) {        /* too expensive to do twice! */
  234. #ifdef QUANT_2PASS_SUPPORTED    /* otherwise can't quantize to supplied map */
  235.     FILE * mapfile;
  236.  
  237.     if ((mapfile = fopen(argv[argn], READ_BINARY)) == NULL) {
  238.       fprintf(stderr, "%s: can't open %s\n", progname, argv[argn]);
  239.       exit(EXIT_FAILURE);
  240.     }
  241.     read_color_map(cinfo, mapfile);
  242.     fclose(mapfile);
  243.     cinfo->quantize_colors = TRUE;
  244. #else
  245.     ERREXIT(cinfo, JERR_NOT_COMPILED);
  246. #endif
  247.       }
  248.  
  249.     } else if (keymatch(arg, "maxmemory", 3)) {
  250.       /* Maximum memory in Kb (or Mb with 'm'). */
  251.       long lval;
  252.       char ch = 'x';
  253.  
  254.       if (++argn >= argc)    /* advance to next argument */
  255.     usage();
  256.       if (sscanf(argv[argn], "%ld%c", &lval, &ch) < 1)
  257.     usage();
  258.       if (ch == 'm' || ch == 'M')
  259.     lval *= 1000L;
  260.       cinfo->mem->max_memory_to_use = lval * 1000L;
  261.  
  262.     } else if (keymatch(arg, "nosmooth", 3)) {
  263.       /* Suppress fancy upsampling */
  264.       cinfo->do_fancy_upsampling = FALSE;
  265.  
  266.     } else if (keymatch(arg, "onepass", 3)) {
  267.       /* Use fast one-pass quantization. */
  268.       cinfo->two_pass_quantize = FALSE;
  269.  
  270.     } else if (keymatch(arg, "outfile", 4)) {
  271.       /* Set output file name. */
  272.       if (++argn >= argc)    /* advance to next argument */
  273.     usage();
  274.       outfilename = argv[argn];    /* save it away for later use */
  275.  
  276.     } else if (keymatch(arg, "scale", 1)) {
  277.       /* Scale the output image by a fraction M/N. */
  278.       if (++argn >= argc)    /* advance to next argument */
  279.     usage();
  280.       if (sscanf(argv[argn], "%d/%d",
  281.          &cinfo->scale_num, &cinfo->scale_denom) != 2)
  282.     usage();
  283.  
  284.     } else {
  285.       usage();            /* bogus switch */
  286.     }
  287.   }
  288.  
  289.   return argn;            /* return index of next arg (file name) */
  290. }
  291.  
  292.  
  293. /*
  294.  * Marker processor for COM markers.
  295.  * This replaces the library's built-in processor, which just skips the marker.
  296.  * We want to print out the marker as text, if possible.
  297.  * Note this code relies on a non-suspending data source.
  298.  */
  299.  
  300. LOCAL(unsigned int)
  301. jpeg_getc (j_decompress_ptr cinfo)
  302. /* Read next byte */
  303. {
  304.   struct jpeg_source_mgr * datasrc = cinfo->src;
  305.  
  306.   if (datasrc->bytes_in_buffer == 0) {
  307.     if (! (*datasrc->fill_input_buffer) (cinfo))
  308.       ERREXIT(cinfo, JERR_CANT_SUSPEND);
  309.   }
  310.   datasrc->bytes_in_buffer--;
  311.   return GETJOCTET(*datasrc->next_input_byte++);
  312. }
  313.  
  314.  
  315. METHODDEF(boolean)
  316. COM_handler (j_decompress_ptr cinfo)
  317. {
  318.   boolean traceit = (cinfo->err->trace_level >= 1);
  319.   INT32 length;
  320.   unsigned int ch;
  321.   unsigned int lastch = 0;
  322.  
  323.   length = jpeg_getc(cinfo) << 8;
  324.   length += jpeg_getc(cinfo);
  325.   length -= 2;            /* discount the length word itself */
  326.  
  327.   if (traceit)
  328.     fprintf(stderr, "Comment, length %ld:\n", (long) length);
  329.  
  330.   while (--length >= 0) {
  331.     ch = jpeg_getc(cinfo);
  332.     if (traceit) {
  333.       /* Emit the character in a readable form.
  334.        * Nonprintables are converted to \nnn form,
  335.        * while \ is converted to \\.
  336.        * Newlines in CR, CR/LF, or LF form will be printed as one newline.
  337.        */
  338.       if (ch == '\r') {
  339.     fprintf(stderr, "\n");
  340.       } else if (ch == '\n') {
  341.     if (lastch != '\r')
  342.       fprintf(stderr, "\n");
  343.       } else if (ch == '\\') {
  344.     fprintf(stderr, "\\\\");
  345.       } else if (isprint(ch)) {
  346.     putc(ch, stderr);
  347.       } else {
  348.     fprintf(stderr, "\\%03o", ch);
  349.       }
  350.       lastch = ch;
  351.     }
  352.   }
  353.  
  354.   if (traceit)
  355.     fprintf(stderr, "\n");
  356.  
  357.   return TRUE;
  358. }
  359.  
  360.  
  361. /*
  362.  * The main program.
  363.  */
  364.  
  365. int
  366. main (int argc, char **argv)
  367. {
  368.   struct jpeg_decompress_struct cinfo;
  369.   struct jpeg_error_mgr jerr;
  370. #ifdef PROGRESS_REPORT
  371.   struct cdjpeg_progress_mgr progress;
  372. #endif
  373.   int file_index;
  374.   FILE * input_file;
  375.   FILE * output_file;
  376.   JDIMENSION num_scanlines;
  377.  
  378.   /* On Mac, fetch a command line. */
  379. #ifdef USE_CCOMMAND
  380.   argc = ccommand(&argv);
  381. #endif
  382.  
  383.   progname = argv[0];
  384.   if (progname == NULL || progname[0] == 0)
  385.     progname = "djpeg";        /* in case C library doesn't provide it */
  386.  
  387.   /* Initialize the JPEG decompression object with default error handling. */
  388.   cinfo.err = jpeg_std_error(&jerr);
  389.   jpeg_create_decompress(&cinfo);
  390.   /* Add some application-specific error messages (from cderror.h) */
  391.   jerr.addon_message_table = cdjpeg_message_table;
  392.   jerr.first_addon_message = JMSG_FIRSTADDONCODE;
  393.   jerr.last_addon_message = JMSG_LASTADDONCODE;
  394.   /* Insert custom COM marker processor. */
  395.   jpeg_set_marker_processor(&cinfo, JPEG_COM, COM_handler);
  396.  
  397.   /* Now safe to enable signal catcher. */
  398. #ifdef NEED_SIGNAL_CATCHER
  399.   enable_signal_catcher((j_common_ptr) &cinfo);
  400. #endif
  401.  
  402.   /* Scan command line to find file names. */
  403.   /* It is convenient to use just one switch-parsing routine, but the switch
  404.    * values read here are ignored; we will rescan the switches after opening
  405.    * the input file.
  406.    * (Exception: tracing level set here controls verbosity for COM markers
  407.    * found during jpeg_read_header...)
  408.    */
  409.  
  410.   file_index = parse_switches(&cinfo, argc, argv, 0, FALSE);
  411.  
  412. #ifdef TWO_FILE_COMMANDLINE
  413.   /* Must have either -outfile switch or explicit output file name */
  414.   if (outfilename == NULL) {
  415.     if (file_index != argc-2) {
  416.       fprintf(stderr, "%s: must name one input and one output file\n",
  417.           progname);
  418.       usage();
  419.     }
  420.     outfilename = argv[file_index+1];
  421.   } else {
  422.     if (file_index != argc-1) {
  423.       fprintf(stderr, "%s: must name one input and one output file\n",
  424.           progname);
  425.       usage();
  426.     }
  427.   }
  428. #else
  429.   /* Unix style: expect zero or one file name */
  430.   if (file_index < argc-1) {
  431.     fprintf(stderr, "%s: only one input file\n", progname);
  432.     usage();
  433.   }
  434. #endif /* TWO_FILE_COMMANDLINE */
  435.  
  436.   /* Open the input file. */
  437.   if (file_index < argc) {
  438.     if ((input_file = fopen(argv[file_index], READ_BINARY)) == NULL) {
  439.       fprintf(stderr, "%s: can't open %s\n", progname, argv[file_index]);
  440.       exit(EXIT_FAILURE);
  441.     }
  442.   } else {
  443.     /* default input file is stdin */
  444.     input_file = read_stdin();
  445.   }
  446.  
  447.   /* Open the output file. */
  448.   if (outfilename != NULL) {
  449.     if ((output_file = fopen(outfilename, WRITE_BINARY)) == NULL) {
  450.       fprintf(stderr, "%s: can't open %s\n", progname, outfilename);
  451.       exit(EXIT_FAILURE);
  452.     }
  453.   } else {
  454.     /* default output file is stdout */
  455.     output_file = write_stdout();
  456.   }
  457.  
  458. #ifdef PROGRESS_REPORT
  459.   start_progress_monitor((j_common_ptr) &cinfo, &progress);
  460. #endif
  461.  
  462.   /* Specify data source for decompression */
  463.   jpeg_stdio_src(&cinfo, input_file);
  464.  
  465.   /* Read file header, set default decompression parameters */
  466.   (void) jpeg_read_header(&cinfo, TRUE);
  467.  
  468.   /* Adjust default decompression parameters by re-parsing the options */
  469.   file_index = parse_switches(&cinfo, argc, argv, 0, TRUE);
  470.  
  471.   /* Start decompressor */
  472.   (void) jpeg_start_decompress(&cinfo);
  473.  
  474.  
  475.   /* Process data */
  476.   {
  477.   unsigned char    *p;
  478.   int i;
  479.   long s;
  480.   unsigned short *v = (unsigned short *)0xc00000;
  481.   unsigned char    *buf;
  482.  
  483.   buf = malloc(cinfo.output_width);
  484.   v += pos_y * 512 + pos_x;
  485.   s = B_SUPER(0);
  486.   while (cinfo.output_scanline < cinfo.output_height && v < (unsigned short *)0xc80000) {
  487.     num_scanlines = jpeg_read_scanlines(&cinfo, &buf, 1);
  488.     p = buf;
  489.     for(i = 0; i < cinfo.output_width && i + pos_x < 512; i++){
  490.       *(v + i) = ((*(p+1) >> 3) << 11) + ((*p >> 3) << 6) + ((*(p+2) >> 3) << 1);
  491.       p += 3;
  492.     }
  493.     v += 512;
  494.   }
  495.   B_SUPER(s);
  496.   free(buf);
  497.   }
  498.  
  499. #ifdef PROGRESS_REPORT
  500.   /* Hack: count final pass as done in case finish_output does an extra pass.
  501.    * The library won't have updated completed_passes.
  502.    */
  503.   progress.pub.completed_passes = progress.pub.total_passes;
  504. #endif
  505.  
  506.   /* Finish decompression and release memory.
  507.    * I must do it in this order because output module has allocated memory
  508.    * of lifespan JPOOL_IMAGE; it needs to finish before releasing memory.
  509.    */
  510.   (void) jpeg_finish_decompress(&cinfo);
  511.   jpeg_destroy_decompress(&cinfo);
  512.  
  513.   /* Close files, if we opened them */
  514.   if (input_file != stdin)
  515.     fclose(input_file);
  516.   if (output_file != stdout)
  517.     fclose(output_file);
  518.  
  519. #ifdef PROGRESS_REPORT
  520.   end_progress_monitor((j_common_ptr) &cinfo);
  521. #endif
  522.  
  523.   /* All done. */
  524.   exit(jerr.num_warnings ? EXIT_WARNING : EXIT_SUCCESS);
  525.   return 0;            /* suppress no-return-value warnings */
  526. }
  527.